﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharpGL;

namespace Graficador3DBinPacking
{
    /// <summary>
    /// The main form class.
    /// </summary>
    public partial class SharpGLForm : Form
    {
        AlgoritmoBinPacking algoritmo;
        Contenedor contenedor;

        double r = 0.1;
        Elemento [] arreglo = new Elemento[50];
        Contenedor[] arregloContenedores = new Contenedor[50];
        
        /// <summary>
        /// Initializes a new instance of the <see cref="SharpGLForm"/> class.
        /// </summary>
        public SharpGLForm()
        {
            int numContenedores = 0;
            InitializeComponent();
            algoritmo = new AlgoritmoBinPacking();
            algoritmo.BinPacking();
            numContenedores = algoritmo.MostrarSolucion(arregloContenedores);
            
            int i = 0;
            int j = 0;
            var nombre = "";

            //MessageBox.Show(numContenedores.ToString());
            for (; i < numContenedores; i++)
            {
                comboContenedor.Items.Add(i);
                

                    foreach (Elemento elemento in arregloContenedores[i]._elementos)
                    {
                

                        j++;
                        arreglo[j] = elemento;
                        //MessageBox.Show(arreglo[i]._volumen.ToString());
                        nombre = "Objeto";
                        nombre += j;
                        //comboBox1.Items.Add(nombre);
                        comboObjeto.Items.Add(j);
                    }

            }
        }

        /// <summary>
        /// Handles the OpenGLDraw event of the openGLControl control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.PaintEventArgs"/> instance containing the event data.</param>
        /*private void openGLControl_OpenGLDraw(object sender, PaintEventArgs e)
        {
            //  Get the OpenGL object.  
            OpenGL gl = openGLControl.OpenGL;    

            //  Clear the color and depth buffer.
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);

            //  Load the identity matrix.
            gl.LoadIdentity();
            
            //  Rotate around the Y axis.
            gl.Rotate(rotation, 0.0f, 1.0f, 0.0f);
           
            int i = 0;
            graficarContenedor(arregloContenedores[i], gl, 1, 1, 1);
            
            foreach (Elemento elemento in arregloContenedores[i]._elementos)
            {
               
                //Random azar = new Random();
                if (i==0) graficarElemento(elemento, gl, 3, 0, 0);
                if (i ==1) graficarElemento(elemento, gl, 0, 1, 0);
                if (i == 2) graficarElemento(elemento, gl, 0, 0, 1);
                if (i == 3) graficarElemento(elemento, gl, 2, 0, 0);
                i++;
            }
            
                       
            //  Nudge the rotation.
            rotation += 3.0f;
        }

        */

        /// <summary>
        /// Handles the OpenGLInitialized event of the openGLControl control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void openGLControl_OpenGLInitialized(object sender, EventArgs e)
        {
            //  TODO: Initialise OpenGL here.

            //  Get the OpenGL object.
            OpenGL gl = openGLControl.OpenGL;

            //  Set the clear color.
            gl.ClearColor(0, 0, 0, 0);
        }

        /// <summary>
        /// Handles the Resized event of the openGLControl control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void openGLControl_Resized(object sender, EventArgs e)
        {
            //  TODO: Set the projection matrix here.

            //  Get the OpenGL object.
            OpenGL gl = openGLControl.OpenGL;

            //  Set the projection matrix.
            gl.MatrixMode(OpenGL.GL_PROJECTION);

            //  Load the identity.
            gl.LoadIdentity();

            //  Create a perspective transformation.
            gl.Perspective(60.0f, (double)Width / (double)Height, 0.01, 100.0);

            //  Use the 'look at' helper function to position and aim the camera.
            gl.LookAt(-5, 5, -5, 0, 0, 0, 0, 1, 0);

            //  Set the modelview matrix.
            gl.MatrixMode(OpenGL.GL_MODELVIEW);
        }

        /// <summary>
        /// The current rotation.
        /// </summary>
        private float rotation = 0.0f;

        private void graficarElemento(Elemento elemento, OpenGL gl, double rojo, double azul, double verde)
        {
            gl.Begin(OpenGL.GL_QUADS);
            gl.Color(rojo, verde, azul);
            //Cara lateral derecha
            
            gl.Vertex(elemento._x * r + elemento._profundidad * r,
                        elemento._y * r + elemento._ancho * r,
                        elemento._z * r);
            gl.Vertex(elemento._x * r, 
                        elemento._y * r + elemento._ancho * r, 
                        elemento._z * r);
            gl.Vertex(elemento._x * r,
                        elemento._y * r + elemento._ancho * r,
                        elemento._z * r + elemento._alto * r);
            gl.Vertex(elemento._x * r + elemento._profundidad * r,
                        elemento._y * r + elemento._ancho * r,
                        elemento._z * r + elemento._alto * r);


           gl.Color(rojo, verde, azul);
            //Cara lateral Izquierda
            gl.Vertex(elemento._x * r + elemento._profundidad * r,
                        elemento._y * r,
                        elemento._z * r + elemento._alto * r);
            gl.Vertex(elemento._x * r, 
                        elemento._y * r, 
                        elemento._z * r + elemento._alto * r);
            gl.Vertex(elemento._x * r,
                        elemento._y * r, 
                        elemento._z * r);
            gl.Vertex(elemento._x * r + elemento._ancho * r,
                        elemento._y * r, 
                        elemento._z * r);


           gl.Color(rojo, verde, azul);
            //Cara Superior
            gl.Vertex(elemento._x * r + elemento._profundidad * r, 
                        elemento._y * r + elemento._ancho * r, 
                        elemento._z * r + elemento._alto * r);

            gl.Vertex(elemento._x * r, 
                        elemento._y * r + elemento._ancho * r,
                        elemento._z * r + elemento._alto * r);
            gl.Vertex(elemento._x * r, 
                        elemento._y * r, 
                        elemento._z * r + elemento._alto * r);
            gl.Vertex(elemento._x * r + elemento._profundidad * r, 
                        elemento._y * r,
                        elemento._z * r + elemento._alto * r);


           gl.Color(rojo, verde, azul);
            //Cara Inferior
            gl.Vertex(elemento._x * r + elemento._profundidad * r, 
                        elemento._y * r,
                        elemento._z * r);
            gl.Vertex(elemento._x * r, 
                        elemento._y * r, 
                        elemento._z * r);
            gl.Vertex(elemento._x * r, 
                        elemento._y * r + elemento._ancho * r,
                        elemento._z * r);
            gl.Vertex(elemento._x * r + elemento._profundidad * r, 
                        elemento._y * r + elemento._ancho * r, 
                        elemento._z * r);


           gl.Color(rojo, verde, azul);
            //Cara Posterior
            gl.Vertex(elemento._x * r, 
                        elemento._y * r + elemento._ancho * r,
                        elemento._z * r + elemento._alto * r);
            gl.Vertex(elemento._x * r, 
                        elemento._y * r + elemento._ancho * r,
                        elemento._z * r);
            gl.Vertex(elemento._x * r, 
                        elemento._y * r, 
                        elemento._z * r);
            gl.Vertex(elemento._x * r, 
                        elemento._y * r, 
                        elemento._z * r + elemento._alto * r);


           gl.Color(rojo, verde, azul);
            //Cara Delantera
            gl.Vertex(elemento._x * r + elemento._profundidad * r, 
                        elemento._y * r + elemento._ancho * r,
                        elemento._z * r);
            gl.Vertex(elemento._x * r + elemento._profundidad * r, 
                        elemento._y * r + elemento._ancho * r, 
                        elemento._z * r + elemento._alto * r);
            gl.Vertex(elemento._x * r + elemento._profundidad * r, 
                        elemento._y * r,
                        elemento._z * r + elemento._alto * r);
            gl.Vertex(elemento._x * r + elemento._profundidad * r, 
                        elemento._y * r,
                        elemento._z * r);

            gl.End();

        }


        private void graficarContenedor(Contenedor contenedor, OpenGL gl, double rojo, double azul, double verde)
        {
            gl.Begin(OpenGL.GL_LINES);
            gl.Color(1.0f, 0.0f, 0.0f);

            //Lineas de cara superior
            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z * r);

            gl.Vertex(contenedor._x * r,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z * r);

            gl.Vertex(contenedor._x * r,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z * r + contenedor._alto * r);

            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z * r + contenedor._alto * r);
            gl.Color(1.0f, 0.0f, 0.0f);

            //Cara Izquierda
            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r,
                        contenedor._z * r + contenedor._alto * r);

            gl.Vertex(contenedor._x * r,
                        contenedor._y * r,
                        contenedor._z * r + contenedor._alto * r);

            gl.Vertex(contenedor._x * r,
                        contenedor._y * r,
                        contenedor._z * r);

            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r,
                        contenedor._z * r);
            gl.Color(1.0f, 0.0f, 0.0f);
            //Cara Superior

            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z * r + contenedor._alto * r);

            gl.Vertex(contenedor._x * r ,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z * r + contenedor._alto * r);
            gl.Vertex(contenedor._x * r ,
                        contenedor._y * r,
                        contenedor._z * r + contenedor._alto * r);

            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r,
                        contenedor._z * r + contenedor._alto * r);
            gl.Color(1.0f, 0.0f, 0.0f);
            //CaraInferior

            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r,
                        contenedor._z * r);
            gl.Vertex(contenedor._x * r,
                        contenedor._y * r ,
                        contenedor._z * r);
            gl.Vertex(contenedor._x * r,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z * r);
            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z * r);
            gl.Color(1.0f, 0.0f, 0.0f);
            //CaraPosterior
            gl.Vertex(contenedor._x * r,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z * r + contenedor._alto * r);
            gl.Vertex(contenedor._x * r,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z *r);
            gl.Vertex(contenedor._x * r,
                        contenedor._y * r,
                        contenedor._z * r);
            gl.Vertex(contenedor._x * r,
                        contenedor._y * r,
                        contenedor._z * r + contenedor._alto * r);
            gl.Color(1.0f, 0.0f, 0.0f);
            //CaraDelantera
            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z * r);
            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r + contenedor._ancho * r,
                        contenedor._z * r + contenedor._alto * r);
            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r,
                        contenedor._z * r + contenedor._alto * r);
            gl.Vertex(contenedor._x * r + contenedor._profundidad * r,
                        contenedor._y * r,
                        contenedor._z * r);
            gl.End();
        }


        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void label5_Click(object sender, EventArgs e)
        {

        }

        private void openGLControl_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {

            
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            
            //MessageBox.Show(comboBox1.SelectedItem.ToString());
            coordenadaX.Text = (arreglo[(int)comboObjeto.SelectedItem]._x).ToString();
            coordenadaY.Text = (arreglo[(int)comboObjeto.SelectedItem]._y).ToString();
            coordenadaZ.Text = (arreglo[(int)comboObjeto.SelectedItem]._z).ToString();

            dimensionesX.Text = (arreglo[(int)comboObjeto.SelectedItem]._profundidad).ToString();
            dimensionesY.Text = (arreglo[(int)comboObjeto.SelectedItem]._ancho).ToString();
            dimensionesZ.Text = (arreglo[(int)comboObjeto.SelectedItem]._alto).ToString();
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void label8_Click(object sender, EventArgs e)
        {

        }

        private void combObjeto_SelectedIndexChanged(object sender, EventArgs e)
        {
            dibujaTodo( arregloContenedores[Convert.ToInt32( comboContenedor.SelectedItem.ToString())]);
                
        }

        private void dibujaTodo(Contenedor contenedor){
            //  Get the OpenGL object.  
            OpenGL gl = openGLControl.OpenGL;

            //  Clear the color and depth buffer.
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);

            //  Load the identity matrix.
            gl.LoadIdentity();

            //  Rotate around the Y axis.
            gl.Rotate(rotation, 0.0f, 1.0f, 0.0f);

            int i = 0;
            graficarContenedor(contenedor, gl, 1, 1, 1);

            foreach (Elemento elemento in contenedor._elementos)
            {

                //Random azar = new Random();
                if (i == 0) graficarElemento(elemento, gl, 3, 0, 0);
                if (i == 1) graficarElemento(elemento, gl, 0, 1, 0);
                if (i == 2) graficarElemento(elemento, gl, 0, 0, 1);
                if (i == 3) graficarElemento(elemento, gl, 2, 0, 0);
                i++;
            }


            //  Nudge the rotation.
            rotation += 3.0f;
            }
    }
}
